﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using ICSharpCode.SharpZipLib.Zip;
using BRM.DataObjects;

namespace BRM.DataAccess
{  
    public class IOHelper
    {
        public delegate void DoProcess(string sFileName);
        //Hàm xử lý copy tất cả các file/folder được chọn khi backup
        public void CopyAll(DirectoryInfo source, DirectoryInfo target)
        {
            
            if (Directory.Exists(target.FullName) == false)
            {
                Directory.CreateDirectory(target.FullName);
            }
            // Copy each file into it’s new directory.
            foreach (FileInfo fi in source.GetFiles())
            {
                //Console.WriteLine(@"Copying {0}\{1}", target.FullName, fi.Name);
                fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
            }

            // Copy each subdirectory using recursion.
            foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
            {
                DirectoryInfo nextTargetSubDir =
                target.CreateSubdirectory(diSourceSubDir.Name);
                CopyAll(diSourceSubDir, nextTargetSubDir);
            }
            //if (DoProcessHandler != null)
            //    DoProcessHandler(source.Name);
        }
        //Hàm xử lý copy folder từ versionItem đến thư mục DirectoryInfo
        public Boolean CopyFolder(BRM.DataObjects.versionItems vi, DirectoryInfo target)
        {
            try
            {
                foreach (BRM.DataObjects.folderItems item1 in vi.detail.folders)
                {
                    if (item1.path != null)
                    {
                        DirectoryInfo sour = new DirectoryInfo(item1.path);
                        DirectoryInfo newtarget = new DirectoryInfo(target+"\\"+item1.name);
                        Directory.CreateDirectory(target + "\\" + item1.name);
                        ClearAttributes(target.FullName);
                        CopyAll(sour, newtarget);
                        if (DoProcessHandler != null)
                            DoProcessHandler(item1.path);
                    }
                }
                return true;
            }
            catch (Exception a)
            {
                return false;
            }
        }
        public event DoProcess DoProcessHandler;
        //Hàm xử lý copy file từ versionItem đến thư mục DirectoryInfo
        public Boolean CopyFile(versionItems vi, DirectoryInfo target)
        {
            try
            {
                
                foreach (fileItems item in vi.detail.files)
                {
                    if (item.path != null)
                    {
                       
                        FileInfo fc = new FileInfo(item.path);
                        FileInfo newFc = new FileInfo(Path.Combine(target.ToString(), item.name));
                        if (File.Exists(newFc.FullName))
                        {
                            File.SetAttributes(newFc.FullName, FileAttributes.Normal);
                            File.Delete(newFc.FullName);
                        }
                            File.Copy(item.path, Path.Combine(target.ToString(), item.name));
                            if (DoProcessHandler != null)
                                DoProcessHandler(item.path);
                    }
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        //Hàm bỏ các thuộc tính không thể copy thành thuộc tính thường để có thể copy file khi backup
        public void ClearAttributes(string sCurrentDir)
        {
            if (Directory.Exists(sCurrentDir))
            {
                string[] asSubDirs = Directory.GetDirectories(sCurrentDir);
                foreach (string dir in asSubDirs)
                    ClearAttributes(dir);
                string[] asFiles = Directory.GetFiles(sCurrentDir);//
                foreach (string sFile in asFiles)
                    File.SetAttributes(sFile, FileAttributes.Normal);
            }
        }
        /// <summary>
        /// Hàm xử lý nén của file/folder
        /// </summary>
        /// <param name="sInputpath">Đường dẫn chứa thư mục ban đầu</param>
        /// <param name="sInputFolderPath">Đường dẫn tới folder cần backup</param>
        /// <param name="sOutputPathAndFile">Tên file trong thư mục ban đầu</param>
        /// <param name="sPassword">Password của file/folder backup</param>
        public void Compress(string sInputpath, string sInputFolderPath, string sOutputPathAndFile, string sPassword)
        {
            ArrayList ar = GenerateFileList(sInputFolderPath); // generate file list

            int TrimLength = (Directory.GetParent(sInputFolderPath)).ToString().Length;
            // find number of chars to remove     // from orginal file path
            TrimLength += 1; //remove '\'
            FileStream ostream;
            byte[] obuffer;
            string sOutPath = sInputpath + @"\" + sOutputPathAndFile;
            ZipOutputStream oZipStream = new ZipOutputStream(File.Create(sOutPath)); // create zip stream
            if (sPassword != null && sPassword != String.Empty)
                oZipStream.Password = sPassword;
            oZipStream.SetLevel(0); // maximum compression
            ZipEntry oZipEntry;
            foreach (string sFil in ar) // for each file, generate a zipentry
            {
                oZipEntry = new ZipEntry(sFil.Remove(0, TrimLength));
                oZipStream.PutNextEntry(oZipEntry);

                if (!sFil.EndsWith(@"/")) // if a file ends with '/' its a directory
                {
                    ostream = File.OpenRead(sFil);
                    obuffer = new byte[ostream.Length];
                    ostream.Read(obuffer, 0, obuffer.Length);
                    oZipStream.Write(obuffer, 0, obuffer.Length);
                    ostream.Close();
                }               
            }          
            oZipStream.Finish();
            oZipStream.Close();
        }

        private static ArrayList GenerateFileList(string sDir)
        {
            ArrayList fils = new ArrayList();
            bool Empty = true;
            foreach (string sFile in Directory.GetFiles(sDir)) // add each file in directory
            {
                fils.Add(sFile);
                Empty = false;
            }

            if (Empty)
            {
                if (Directory.GetDirectories(sDir).Length == 0)
                // if directory is completely empty, add it
                {
                    fils.Add(sDir + @"/");
                }
            }

            foreach (string sDirs in Directory.GetDirectories(sDir)) // recursive
            {
                foreach (object obj in GenerateFileList(sDirs))
                {
                    fils.Add(obj);
                }
            }
            return fils; // return file list
        }

          /// <summary>
          /// Hàm xử lý giải nén file/folder
          /// </summary>
          /// <param name="sZipPathAndFile">Đường dẫn tới file nén</param>
          /// <param name="sOutputFolder">Đường dẫn khi giải nén file (nơi chứa file khi giải nén)</param>
          /// <param name="sPassword">Password của file nén</param>
          /// <param name="sDeleteZipFile">Delete file nén</param>
          public void Decompress(string sZipPathAndFile, string sOutputFolder, string sPassword, bool sDeleteZipFile)
          {
            ZipInputStream s = new ZipInputStream(File.OpenRead(sZipPathAndFile));
            if (sPassword != null && sPassword != String.Empty)
                s.Password = sPassword;
            ZipEntry theEntry;
            string sTmpEntry = String.Empty;
            while ((theEntry = s.GetNextEntry()) != null)
            {
                string sDirectoryName = sOutputFolder;
                string sFileName = Path.GetFileName(theEntry.Name);
                // create directory 
                if (sDirectoryName != "")
                {
                    Directory.CreateDirectory(sDirectoryName);
                }
                if (sFileName != String.Empty)
                {
                    if (theEntry.Name.IndexOf(".ini") < 0)
                    {
                        string sFullPath = sDirectoryName + "\\" + theEntry.Name;
                        sFullPath = sFullPath.Replace("\\ ", "\\");
                        string sFullDirPath = Path.GetDirectoryName(sFullPath);
                        if (!Directory.Exists(sFullDirPath)) Directory.CreateDirectory(sFullDirPath);
                        FileStream streamWriter = File.Create(sFullPath);
                        int size = 2048;
                        byte[] data = new byte[2048];
                        while (true)
                        {
                            size = s.Read(data, 0, data.Length);
                            if (size > 0)
                            {
                                streamWriter.Write(data, 0, size);
                            }
                            else
                            {
                                break;
                            }
                        }
                        streamWriter.Close();
                    }
                }
            }
            s.Close();
            if (sDeleteZipFile)
                File.Delete(sZipPathAndFile);
        }
    }
}
